Where: Size is how many items in the block (bytes, words or doubles).
Pattern is the value of each item, default = 0.
Examples of use:
dbb 1024, &ff
dbw 100, %0110110101010100
dbd 512
Including binary files (data-files)
-----------------------------------
INCBIN Include Binary file.
Syntax: INCBIN <filename>
Where: filename is the data-file to insert.
Notice: Space is automatically allocated for the file, and is byte-aligned.
Examples of use:
.SinTab incbin <tmp$path>.Tables.SinusTable
Case sensitivity
----------------
All assembler syntax is case insensitive.
All macros, labels & assembler variables are case sensitive.
Register binding
----------------
Registers (r0-r15 or f0-f7) can be types in several ways:
• Using the hard-coded "r0"-"r15" or "f0"-"f7".
• By typing any number, e.g. "8", "%0011", "&a" or similar.
• By using a variable defined by #set, e.g. "MyReg", "Result".
• In macros, "m0"-"mn".
Operators
---------
The following operators are implemented:
* Multiplication / Division
+ Addition - Subtraction
<< Shift left EOR Exclusive OR
( Start Sub-expression ) End Sub-expression
== Test for equal != or <> Test for not-equal
<= or =< Test for less-or-equal >= or => Test for greater-or-equal
> Test for less-then > Test for greater-then
Extensions
----------
extASM has been extended in many ways to offer greater value :
The instruction ORR can be spelled OR if you prefer.
Hex numbers can be preceded with either "&" or the widely used "$".
Octal values are supported, and should be preceded with "@".
All labels start with a dot (.) as usual, but
Local labels start their name with underscore (_). e.g. "._Loop"
Most ALU instructions will be auto-expanded if the immediate constant is too big to be handled by a single instruction. The only instructions that cannot be auto-expanded are CMP, CMN, TST & TEQ. Future versions will provide these through the use of temp-registers.
LDR & STR using labels will be auto-expanded if the 4KB range is exceeded, and will give a new range of 1MB. >1MB ranges might be implemented at a later date, but this should not be necessary, most executables are well below 1MB.
TEMP & LOCK are used to tell the assembler that some registers can be temporarily used by macros or for auto-expanding, eliminating the need to save registers on the stack when extra registers are needed.
Local Labels
------------
Local labels are very useful in assembler programming, because they make it possible to use the same label-name many times. When defining a local label, the first character of the label-name should be an underscore (_). The scope of the local label (where it is legal) is only between two normal variables. Here is an example:
.Skip_Blanks ; R0 = char, R10-> next char
STMFD R13!,{R14 }
._Loop ; define local label
CMP R0,#" " ; search for space-char
CMPNE R0,#&09 ; ... or a TAB-char
LDREQB R0,[R10],#1
BEQ _Loop ; use local label
LDMFD R13!,{PC}^
Macros
------
The use of macros make it easier to do routinely things, and can be a very powerful tool in making complex code. The macro can be defined anywhere in the source, and it is smart to have a standard file of all your standard macros, so that you can easily include this into all other programs you make.
Currently, macros can take two different passing-parameters, and use three different parameter. The additional use-parameter is temp-registers.
The two passing-parameter types are:
Mx Macro register (Mx = passed Rx)
Cx Macro constant (Cx = passed constant)
The last use-only parameter is:
Tx Macro temp-register.
The passing-parameters are the arguments sent from the source upon using the macro, and translates to the Mx/Cx inside the macro. The macro temp-regs are additional registers that the macro needs to do the job. The temp-registers will be allocated by the assembler automatically. Here's a simple macro example.
.Start
mov r1,r2 ; normal instruction
inc3 r1,r2,r8,128,256,512 ; use macro
movs pc,r14
.End
macro inc m0,m1,m2,c0,c1,c2 ; define macro
{
add m0,m0,#c0
add m1,m1,#c1
add m2,m2,#c2
}
NOTE: You should not use any variables begining with "m" or "t" for register binding, as this will conflict with the "mx" & "tx" macro register alias. Also, do not use any constant-variables (or labels) starting with "c" as this will conflict with the "cx" macro constant alias.
Future versions will implement macros in a different way - which will eliminate this problem.
Structures
----------
Structures let you combine several data-types to make a complec data-type. Most high-level languages support such mechanisms, and now you can benefit from this usefull technique in assembly level programming as well.
Here's how to make a simple structure:
struct mouse {
.x_pos dcd 0
.y_pos dcd 0
.buttons dcd 0
.size ; .size = size of struct! (end...)
}
To allocate some static space for an instance of this data-type do this:
.MouseBlock
dbb mouse.size,0 ; declare block or rigth size
align ; just in case it wasn't aligned...
Easy! Now, to address directly into this area, here's how:
swi OS_Mouse
str r0,MouseBlock + mouse.x_pos
str r1,MouseBlock + mouse.y_pos
str r2,MouseBlock + mouse.buttons
Or, if you have a register pointing to the data-area, you can:
swi OS_Mouse
adr r9,MouseBlock
str r0,[r9,#mouse.x_pos]
str r1,[r9,#mouse.y_pos]
str r2,[r9,#mouse.buttons]
Extra Internal Instructions
---------------------------
ADR Get address.
Syntax: ADR[CC] Rd, <Label>
Operation: Rd = Address of <label>
Examples of use:
adr r1,Data_Block
DIV Integer division.
Syntax: DIV[CC] Rd, Rn, Rs
Operation: Rd = Rn DIV Rs
Rn = Rn MOD Rs
Notice: Rd, Rn & Rs must be uniqe.
Extra: Uses 1 Temp Register.
Examples of use:
div r1,r4,r7
divle r10,r11,r12
EXG Exhange contents of two integer registers.
Syntax: EXG[CC][S] Rd,Rn
Operation: Rd = old Rn
Rn = old Rd
Notice: Rd must be different from Rn.
Examples of use:
exg r1,r2
exglt r3,r9
exgnes r0,r1
Temp Register Management
------------------------
TEMP Mark a register as unused, so it can be used as a TempReg
Syntax: TEMP RegList
Where: Reglist is a list of registers, or register-ranges.
Notice: The contents of Rd are unsafe until it is LOCK'ed again.
Examples of use:
temp r0
temp r1,r2,r8-r12
LOCK Reclaim a register after a it has been TEMP'ed.
Syntax: LOCK RegList
Where: Reglist is a list of registers, or register-ranges.
Notice The contents of Rd is safe after this point.
Examples of use:
lock r0
lock r1,r2,r8-r12
Stack setup
-----------
The assembler assumes there is a valid full-descending stack at R13. This is for saving temporary registers during macros or auto-expansion of out-of-range instructions where no temp-regs are available.
Here is an example of how to setup a valid stack:
#set StackSize = 1024 ; how large stack do we want?
.Start
b Main ; jump over the stack
.Stack_Ceiling ; top-of-stack
dbb StackSize,0 ; allocate stack space here
.Stack_Floor ; bottom-of-stack
.Old_Stack dcd 0 ; place to store old r13
.Main
str r13,Old_Stack ; save old r13
adr r13,Stack_Floor ; r13-> new stack
stmfd r13!,{r0-r12,r14} ; push all registers on our stack
.Begin
; normal code ; put your program here
.End
ldmfd r13!,{r0-r12,r14} ; pop all registers from our stack